#include "Backend.h"

#ifdef VTK_ENABLE_OSPRAY
#include "OSPRay/OSPRayBackend.h"
#endif
#ifdef VTK_ENABLE_VISRTX
#include "VisRTX/VisRTXBackend.h"
#endif

#include "RTWrapper.h"
#include "vtksys/SystemTools.hxx"
#include "vtkLogger.h"

#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <sstream>

#ifdef VTK_ENABLE_VISRTX
RTW::VisRTXBackend* rtwVisRTXBackend = nullptr;
#endif

#ifdef VTK_ENABLE_OSPRAY
RTW::OSPRayBackend* rtwOSPRayBackend = nullptr;
#endif

void rtwInit()
{
#ifdef VTK_ENABLE_VISRTX
        const bool dontSkipVisRTXInit = vtksys::SystemTools::GetEnv("VTK_DEBUG_SKIP_VISRTX_CHECK") == nullptr;

    if (!rtwVisRTXBackend)
    {
        vtkLogF(TRACE, "VisRTX/OptiX backend enabled in CMake configuration. Checking for support...");
        if(dontSkipVisRTXInit)
        {
            rtwVisRTXBackend = new RTW::VisRTXBackend();
            if (rtwVisRTXBackend->Init() != RTW_NO_ERROR)
            {
                vtkLogF(TRACE, "Failed to initialize RTW_VisRTX backend.");
                rtwVisRTXBackend->Shutdown();
                delete rtwVisRTXBackend;
                rtwVisRTXBackend = nullptr;
            }
        }
        else
            vtkLogF(TRACE, "VisRTX/OptiX backend skipped due to environment variable VTK_DEBUG_SKIP_VISRTX_CHECK");
    }
#else
    vtkLogF(TRACE, "VisRTX/OptiX backend disabled via CMake configuration for this build");
#endif
#ifdef VTK_ENABLE_OSPRAY
        const bool dontSkipOSPRAYInit = vtksys::SystemTools::GetEnv("VTK_DEBUG_SKIP_OSPRAY_CHECK") == nullptr;

    if (!rtwOSPRayBackend && dontSkipOSPRAYInit)
    {
        rtwOSPRayBackend = new RTW::OSPRayBackend();
        if (rtwOSPRayBackend->Init() != RTW_NO_ERROR)
        {
            // std::cerr << "WARNING: Failed to initialize RTW OSPRay backend.\n";
            rtwOSPRayBackend->Shutdown();
            delete rtwOSPRayBackend;
            rtwOSPRayBackend = nullptr;
        }
    }
#endif
}

RTW::Backend *rtwSwitch(const char *name)
{
    if (!strcmp(name, "optix pathtracer"))
    {
#ifdef VTK_ENABLE_VISRTX
        return rtwVisRTXBackend;
#endif
    }
    else
    {
#ifdef VTK_ENABLE_OSPRAY
        return rtwOSPRayBackend;
#endif
    }
    return nullptr;
}

void rtwShutdown()
{
#ifdef VTK_ENABLE_VISRTX
    if (rtwVisRTXBackend)
    {
        rtwVisRTXBackend->Shutdown();
    }
    rtwVisRTXBackend=nullptr;
#endif
#ifdef VTK_ENABLE_OSPRAY
    if (rtwOSPRayBackend)
    {
        rtwOSPRayBackend->Shutdown();
    }
    rtwOSPRayBackend=nullptr;
#endif
}

std::set<RTWBackendType> rtwGetAvailableBackends()
{
    rtwInit();
    std::set<RTWBackendType> result;
#ifdef VTK_ENABLE_VISRTX
    if (rtwVisRTXBackend)
        result.insert(RTW_BACKEND_VISRTX);
#endif

#ifdef VTK_ENABLE_OSPRAY
    if (rtwOSPRayBackend)
        result.insert(RTW_BACKEND_OSPRAY);
#endif
    return result;
}
